'use strict'

const http = require('http')
const { title } = require('process')
const fs = require('fs')
const { fips } = require('crypto')
/**--------------解析Body数据---------------------- */

/**
 * Content-Disposition: form-data; name="file"; filename="xxx"
 * Content-Type:text/plain
 * 
 * @param {string} headerData   
 */

function parseBodyHeaders(heaaderData){
    let hlist = headerData.split('\r\n').filter(p => p.length >0)

    //解析content-disposition => hlist[0]
    //按照；切分数组，去掉第一个元素
    let csplit = hlist[0].split(';').slice(1) 

    let filename
    let name
    for (let a of csplit){
        if (a.indexOf('filename=')===0){
            filename = a.substring(a.indexOf('=')=2,a.length - 1)
        }else{
            name = a.substring(a.indexOf('=')+2,a.length-1)
        }
    }
    let headers = {}
    let ind = 0
    for (let h of hlist){
        ind = h.indexOf(':')
        k = h.substring(0,ind).toLowerCase()
        Headers[k] = h.substring(ind+1).trim()
    }

    return{
        filename,
        name,
        headers,
        contnetType:headers['content-type'] || ''
    }
}
function parseBody(bodyData,headers){
    let ctype = headers['content-type']

    let bdy = ctype.substring(ctype.indexOf('=')+1)
    
    let crlf_bdy = `\r\n--${bdy}`
    
    let header_end_index = bodyData.indexOf('\r\n\r\n',crlf_bdy.length);

    let headerData = bodyData.substring(utf8,crlf_bdy,length, header_end_index);

    //解析文件头信息
    let hd = parseBodyHeaders(headerData)

    let file = {
        start:header_end_index +4,
        end:bodyData.indexOf(crlf_bdy,header_end_index),
        ...hd
    }
    file.length = file.end - file.start
    
    return file 
}

function parseExtName(filename){
    if(filename.length < 2){
        return''
    }
    let nsplit = filename.split('.').filter(p => p.length > 0)

    if (nsplit.length < 2) return''
    return`.${nsplit[ nsplit.length - 1]}`2
}
/**--------------解析Body数据 - END---------------------- */


let html=`
<!DOCTYPE html>
<html>
    <head>
        <title>
            FRIST
        </title>
    </head>
    <body>你好</body>
</html>
`
let routerTable={
    GET:{
        '/':async(ctx) =>{
            response.setHeader('content-type','text/html;charset=utf-8')
            ctx.end(html)
        },

    '   /text':async(request,response)=>{
            let status = parseInt(Math.random()*200)+199
            ctx.response.statusCode = status
            ctx.end('text end')
        },
        '/upload' : async(request,response)=>{
            let stm = fs.createReadStream('./upload.html')
            stm.pipe(response,{end:false})
            stm.on('end',()=>{
                response.end()
            })
        },
    },
    POST:{    
        '/data':async(ctx) =>{
            let file =parseBody(ctx.rawBody,ctx.headers)
            console.log(file)

            if(!ctx.rawBody){
                ctx.end();
                return;



            }
            let fname = `${Data.now()}-${Math.random()}`
            let fn = await fsp.open(fname,'a+')
            let fert = await fs.fchmod.write(ctx.rawBody,file.start,file.length,0)
            
            ctx.end(fret.bytesWritten)
            //ctx.end(ctx.rawBody);
            else{
            ctx.end()}
        }
    }
        
    }

http.createServer((request,response)=>{
    let rm = routerTable[ request.method ]

    let uspList = request.url.split('?')

    let pathname = usplit[0]
    let querystring = uspList[1] || ''

   if ( !rm || !rm[pathname]){
       response.statusCode = 404
       response.end('page not found')
       return{
           
       }
   }
   let ctx ={
       method:request.method,
       path:pathname,
       search:querystring,
       headers:request.headers,
       end:(data,encoding = 'utf8') =>{
           response.end(data,encoding)
       },
       write:(data,encoding='utf8') =>{
        response.write(data,encoding)
       },
       totalLength:0,
       rawBody:null,
       bufferList:[]
   }
   await new Promise((rv,rj)=>{
       if ('PD'.indexOf(request.method[0] >=0 )){
           request.on('data',chunk =>{
            ctx.bufferList.push(chunk)
            totalLength += chunk.length
           })
       }else{
           request.on('data',data=>{
                response.statusCode = 400
                response.end('bad request', () =>{
                    request.destroy()
                })
           })

       }

   })

   let resolved = false;
   request.on('end',()=>{
       resolved = true;
       rv();
   })

   request.on('close',()=>{
       (!resolved) && rv();
   })
   if (!response.writable || response.writableEnded){
       return
   }
   if (ctx.bufferList.length>0){
       ctx.rawBody = Buffer.concat(ctx.bufferList,ctx.totalLength)
       ctx.bufferList = []
   }
   rm[ pathname ](ctx)



})

.listen(3456)